/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package questionbook.manager;

import com.clarkparsia.pellet.owlapiv3.PelletReasoner;
import com.clarkparsia.pellet.owlapiv3.PelletReasonerFactory;
import java.io.File;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.semanticweb.owlapi.apibinding.OWLManager;
import org.semanticweb.owlapi.model.AddAxiom;
import org.semanticweb.owlapi.model.IRI;
import org.semanticweb.owlapi.model.OWLAxiom;
import org.semanticweb.owlapi.model.OWLClassExpression;
import org.semanticweb.owlapi.model.OWLDataFactory;
import org.semanticweb.owlapi.model.OWLDifferentIndividualsAxiom;
import org.semanticweb.owlapi.model.OWLNamedIndividual;
import org.semanticweb.owlapi.model.OWLObjectProperty;
import org.semanticweb.owlapi.model.OWLOntology;
import org.semanticweb.owlapi.model.OWLOntologyManager;
import org.semanticweb.owlapi.reasoner.ConsoleProgressMonitor;
import org.semanticweb.owlapi.reasoner.Node;
import org.semanticweb.owlapi.reasoner.OWLReasonerConfiguration;
import org.semanticweb.owlapi.reasoner.SimpleConfiguration;
import org.semanticweb.owlapi.util.InferredAxiomGenerator;
import org.semanticweb.owlapi.util.InferredClassAssertionAxiomGenerator;
import org.semanticweb.owlapi.util.InferredOntologyGenerator;
import org.semanticweb.owlapi.util.InferredPropertyAssertionGenerator;
import org.semanticweb.owlapi.util.InferredSubClassAxiomGenerator;
import questionbook.Configuration.QuestionbookConfiguration;
import questionbook.model.Answer;
import questionbook.model.AnswerClass;
import questionbook.model.Comment;
import questionbook.model.Person;
import questionbook.model.UserClass;
import questionbook.service.AnswerService;
import questionbook.service.AnswerServiceBean;
import questionbook.service.CommentService;
import questionbook.service.CommentServiceBean;
import questionbook.service.PersonService;
import questionbook.service.PersonServiceBean;
import questionbook.standard.Qbook;

/**
 * The ReasoningManager is a Singleton Class which provides Access to
 * the Funcionality of the Manchester OWL API and the Pellet Reasoner
 *
 *
 * @author stefanstift
 */
public class ReasoningManager {

    private static ReasoningManager instance;
    private String fileStoreage = QuestionbookConfiguration.getInstance().getStorePath();

    protected ReasoningManager() {
    }

    public static ReasoningManager getInstance() {
        if (instance == null) {
            instance = new ReasoningManager();
        }

        return instance;
    }

    /**
     * This method loads the Ontology and the Reasoner in order
     * to assert all possible Triples. All RDFS and OWL Axioms
     * get processed according to the ReasoningType that is
     * specified. After the assertion the Triples are saved in
     * the Store.
     *
     * @param type Defines which Kind of Axioms are part of the Reasoning Process
     */
    public void processReasoning(ReasoningType type) {
        File ontFile = null;

        try {
            ontFile = new File(this.fileStoreage);

            // Load the Ontology
            OWLOntologyManager manager = OWLManager.createOWLOntologyManager();
            OWLOntology ont = manager.loadOntologyFromOntologyDocument(ontFile);

            // Create the Reasoner
            PelletReasonerFactory reasonerFactory = new PelletReasonerFactory();
            ConsoleProgressMonitor progressMonitor = new ConsoleProgressMonitor();
            OWLReasonerConfiguration config = new SimpleConfiguration(progressMonitor);

            // Load the Ontology into the Reasoner
            PelletReasoner reasoner = reasonerFactory.createReasoner(ont, config);
            reasoner.precomputeInferences();

            List<InferredAxiomGenerator<? extends OWLAxiom>> gens =
                    new ArrayList<InferredAxiomGenerator<? extends OWLAxiom>>();


            // Assign the Axiosm that get processed
            if(type == ReasoningType.Properties)
                gens.add(new InferredPropertyAssertionGenerator());
            else if(type == ReasoningType.Classes)
            {
                gens.add(new InferredSubClassAxiomGenerator());
                gens.add(new InferredClassAssertionAxiomGenerator());
            }
            else
            {
                gens.add(new InferredPropertyAssertionGenerator());
                gens.add(new InferredSubClassAxiomGenerator());
                gens.add(new InferredClassAssertionAxiomGenerator());
            }

            // Do the Reasoning
            InferredOntologyGenerator iog = new InferredOntologyGenerator(reasoner, gens);
            // Save the inferred Triples
            iog.fillOntology(manager, ont);
            manager.saveOntology(ont);
            

        } catch (Exception re) {
            re.printStackTrace();
        }

        StoreManager.getInstance().reloadStore();
    }

    /**
     * This method closes the World for a specified Answer. This means that all
     * Comments for this Answer get loaded and inserted in the Store with the
     * Property "owl:differentFrom". This is necessary in order to process an 
     * cardinality Restriction over the Comments.
     *
     *
     * @param a the Answers for which thw World gets closed
     */
    private void closeWorld (Answer a)
    {
        File ontFile = null;

        try {

            ontFile = new File(this.fileStoreage);

            OWLOntologyManager manager = OWLManager.createOWLOntologyManager();
            OWLOntology ont = manager.loadOntologyFromOntologyDocument(ontFile);
            OWLDataFactory dataFactory = manager.getOWLDataFactory();

            PelletReasonerFactory reasonerFactory = new PelletReasonerFactory();
            ConsoleProgressMonitor progressMonitor = new ConsoleProgressMonitor();
            OWLReasonerConfiguration config = new SimpleConfiguration(progressMonitor);

            PelletReasoner reasoner = reasonerFactory.createReasoner(ont, config);
            reasoner.precomputeInferences();

            CommentService commentService = new CommentServiceBean();
            List<Comment> comments = commentService.getByAnswer(a);

            Set<OWLNamedIndividual> individuals = new HashSet<OWLNamedIndividual>();

            for(Comment c : comments)
            {
                individuals.add(dataFactory
                        .getOWLNamedIndividual(IRI.create(c.getUri()
                        .stringValue())));
            }

            OWLDifferentIndividualsAxiom diffAx =
                    dataFactory.getOWLDifferentIndividualsAxiom(individuals);
            AddAxiom addAx = new AddAxiom(ont, diffAx);
            manager.applyChange(addAx);
            manager.saveOntology(ont);

        } catch (Exception re) {
            re.printStackTrace();
        }

        this.processReasoning(ReasoningType.All);
    }

    /**
     * This method closes the World for a specified Person. This means that all
     * Answers for this Person get loaded and inserted in the Store with the
     * Property "owl:differentFrom". This is necessary in order to process an
     * cardinality Restriction over the Answers.
     *
     * @param p the Person for which the World gets closed
     */
    private void closeWorld (Person p)
    {
        File ontFile = null;

        try {

            ontFile = new File(this.fileStoreage);

            OWLOntologyManager manager = OWLManager.createOWLOntologyManager();
            OWLOntology ont = manager.loadOntologyFromOntologyDocument(ontFile);
            OWLDataFactory dataFactory = manager.getOWLDataFactory();


            PelletReasonerFactory reasonerFactory = new PelletReasonerFactory();
            ConsoleProgressMonitor progressMonitor = new ConsoleProgressMonitor();
            OWLReasonerConfiguration config = new SimpleConfiguration(progressMonitor);

            PelletReasoner reasoner = reasonerFactory.createReasoner(ont, config);
            reasoner.precomputeInferences();

            AnswerService answerService = new AnswerServiceBean();
            List<Answer> answers = answerService.getByPerson(p);

            Set<OWLNamedIndividual> individuals = new HashSet<OWLNamedIndividual>();

            for(Answer a : answers)
            {
                individuals.add(dataFactory.getOWLNamedIndividual(IRI.create(a.getUri().stringValue())));
            }

            OWLDifferentIndividualsAxiom diffAx = dataFactory.getOWLDifferentIndividualsAxiom(individuals);
            AddAxiom addAx = new AddAxiom(ont, diffAx);

            // TODO: SOLLTE MAN HIER NOCH BEDENKEN
//            RemoveAxiom remAx = new RemoveAxiom(ont, diffAx);

            manager.applyChange(addAx);
            manager.saveOntology(ont);

        } catch (Exception re) {
            re.printStackTrace();
        }

        this.processReasoning(ReasoningType.All);
    }

    /**
     * Creates the Cardinality Restrictions from the number of
     * given Comments and prcesses this Restrictions in order to
     * get the right Class for the Answer
     *
     * @param a the Answer which gets classified
     */
    public void classify(Answer a)
    {
        this.closeWorld(a);

        File ontFile = null;
        AnswerService answerService = new AnswerServiceBean();
        CommentService commentService = new CommentServiceBean();
        PersonService personService = new PersonServiceBean();

        try {

            answerService.removeClassification(a);
            answerService.flush();
            personService.removeAnswerClass(a);
            personService.removeCharma(a);
            personService.flush();
            
            ontFile = new File(this.fileStoreage);

            OWLOntologyManager manager = OWLManager.createOWLOntologyManager();
            OWLOntology ont = manager.loadOntologyFromOntologyDocument(ontFile);
            OWLDataFactory dataFactory = manager.getOWLDataFactory();


            PelletReasonerFactory reasonerFactory = new PelletReasonerFactory();
            ConsoleProgressMonitor progressMonitor = new ConsoleProgressMonitor();
            OWLReasonerConfiguration config = new SimpleConfiguration(progressMonitor);

            PelletReasoner reasoner = reasonerFactory.createReasoner(ont, config);
            reasoner.precomputeInferences();

            List<Comment> comments = commentService.getByAnswer(a);
           
            Double factorHigh = comments.size() * 0.8;
            int cardinalityHigh = (int) Math.ceil(factorHigh);
            Double factorLow = comments.size() * 0.5;
            int cardinalityLow = (int) Math.ceil(factorLow);

            System.out.println("Answer Cardinality 80% = " + cardinalityHigh);
            System.out.println("Answer Cardinality 50% = " + cardinalityLow);

            OWLObjectProperty positiveProperty = dataFactory.getOWLObjectProperty(IRI.create(Qbook.getInstance().getPositiveURI().stringValue()));
            OWLClassExpression positiveClass = dataFactory.getOWLObjectMinCardinality(cardinalityLow, positiveProperty);

            OWLObjectProperty negativeProperty = dataFactory.getOWLObjectProperty(IRI.create(Qbook.getInstance().getNegativeURI().stringValue()));
            OWLClassExpression negativeClass = dataFactory.getOWLObjectMinCardinality(cardinalityLow, negativeProperty);

            OWLObjectProperty sureRightProperty = dataFactory.getOWLObjectProperty(IRI.create(Qbook.getInstance().getSureRightURI().stringValue()));
            OWLClassExpression sureRightClass = dataFactory.getOWLObjectMinCardinality(cardinalityHigh, sureRightProperty);

            OWLObjectProperty sureWrongProperty = dataFactory.getOWLObjectProperty(IRI.create(Qbook.getInstance().getSureWrongURI().stringValue()));
            OWLClassExpression sureWrongClass = dataFactory.getOWLObjectMinCardinality(cardinalityHigh, sureWrongProperty);

            reasoner.prepareReasoner();

            // Überprüfung ob >= 80% der Comments SureRight sind - wenn ja wird die Antowrt
            // als SuperAnswer klassifiziert

            for(Node<OWLNamedIndividual> cl : reasoner.getInstances(sureRightClass, true))
            {
                System.out.println("SURE RIGHT REACHED card high");

                for(OWLNamedIndividual ind : cl.getEntities())
                {
                    if(ind.getIRI().toString().equals(a.getUri().stringValue()))
                    {
                        if(a.getAnswerer().getUserClass() != null &&
                           a.getAnswerer().getUserClass() == UserClass.ExpertUser)
                        {
                            a.setAnswerClass(AnswerClass.ExpertAnswer);
                        }
                        else
                            a.setAnswerClass(AnswerClass.SuperAnswer);

                        answerService.updateClassification(a);
                        personService.persistAnswerClass(a);
                        personService.persistCharma(a, Qbook.getInstance().getHasGoodCharmaURI());
                        answerService.flush();

                        this.processReasoning(ReasoningType.Classes);
                        return;
                    }
                }
            }

            // Überprüfung ob >= 50% der Comments Positive sind - wenn ja wird die Antowrt
            // als TrustAnswer klassifiziert

            for(Node<OWLNamedIndividual> cl : reasoner.getInstances(positiveClass, true))
            {
                for(OWLNamedIndividual ind : cl.getEntities())
                {
                    if(ind.getIRI().toString().equals(a.getUri().stringValue()))
                    {
                        a.setAnswerClass(AnswerClass.TrustAnswer);
                        answerService.updateClassification(a);
                        personService.persistAnswerClass(a);

                        if(a.getAnswerType().getUri().equals(Qbook.getInstance().getSureURI()))
                            personService.persistCharma(a, Qbook.getInstance().getHasGoodCharmaURI());
                        else
                           personService.persistCharma(a, Qbook.getInstance().getHasMediateCharmaURI());
                        
                        answerService.flush();
                        this.processReasoning(ReasoningType.Classes);
                        return;
                    }
                }
            }

            // Überprüfung ob >= 80% der Comments SureWrong sind - wenn ja wird die Antowrt
            // als BadAnswer klassifiziert

            for(Node<OWLNamedIndividual> cl : reasoner.getInstances(sureWrongClass, true))
            {
                for(OWLNamedIndividual ind : cl.getEntities())
                {
                    if(ind.getIRI().toString().equals(a.getUri().stringValue()))
                    {
                        if(a.getAnswerer().getUserClass() != null &&
                           a.getAnswerer().getUserClass() == UserClass.BeginnerUser)
                        {
                            a.setAnswerClass(AnswerClass.IgnoreAnswer);
                        }
                        else
                            a.setAnswerClass(AnswerClass.BadAnswer);
                        
                        answerService.updateClassification(a);
                        personService.persistAnswerClass(a);
                        personService.persistCharma(a, Qbook.getInstance().getHasBadCharmaURI());
                        answerService.flush();
                        this.processReasoning(ReasoningType.Classes);
                        return;
                    }
                }
            }

            // Überprüfung ob >= 50% der Comments Negative sind - wenn ja wird die Antowrt
            // als DoubtAnswer klassifiziert

            for(Node<OWLNamedIndividual> cl : reasoner.getInstances(negativeClass, true))
            {
                for(OWLNamedIndividual ind : cl.getEntities())
                {
                    if(ind.getIRI().toString().equals(a.getUri().stringValue()))
                    {   
                        a.setAnswerClass(AnswerClass.DoubtAnswer);
                        answerService.updateClassification(a);
                        personService.persistAnswerClass(a);

                        if(a.getAnswerType().getUri().equals(Qbook.getInstance().getSureURI()))
                            personService.persistCharma(a, Qbook.getInstance().getHasBadCharmaURI());
                        else
                           personService.persistCharma(a, Qbook.getInstance().getHasMediateCharmaURI());

                        answerService.flush();
                        this.processReasoning(ReasoningType.Classes);
                        return;
                    }
                }
            }
            // Bei allen andern Fällen wird die Antword als StdAnswer klassifiziert

            a.setAnswerClass(AnswerClass.StdAnswer);
            answerService.updateClassification(a);
            answerService.flush();
            this.processReasoning(ReasoningType.Classes);

        } catch (Exception re) {
            re.printStackTrace();
        }
    }

    /**
     * Creates the Cardinality Restrictions from the number of
     * given Answers and prcesses this Restrictions in order to
     * get the right Class for the Person
     *
     * @param p the Person which gets classified
     */
    public void classify(Person p)
    {
        this.closeWorld(p);

        File ontFile = null;
        AnswerService answerService = new AnswerServiceBean();
        PersonService personService = new PersonServiceBean();

        try {

            personService.removeUserClass(p);
            personService.flush();

            ontFile = new File(this.fileStoreage);

            OWLOntologyManager manager = OWLManager.createOWLOntologyManager();
            OWLOntology ont = manager.loadOntologyFromOntologyDocument(ontFile);
            OWLDataFactory dataFactory = manager.getOWLDataFactory();


            PelletReasonerFactory reasonerFactory = new PelletReasonerFactory();
            ConsoleProgressMonitor progressMonitor = new ConsoleProgressMonitor();
            OWLReasonerConfiguration config = new SimpleConfiguration(progressMonitor);

            PelletReasoner reasoner = reasonerFactory.createReasoner(ont, config);
            reasoner.precomputeInferences();

            List<Answer> answers = answerService.getByPerson(p);

            Double factor80 = answers.size() * 0.8;
            int cardinality80 = (int) Math.ceil(factor80);
            Double factor50 = answers.size() * 0.5;
            int cardinality50 = (int) Math.ceil(factor50);
            Double factor90 = answers.size() * 0.9;
            int cardinality90 = (int) Math.ceil(factor90);
            Double factor60 = answers.size() * 0.6;
            int cardinality60 = (int) Math.ceil(factor60);
            Double factor40 = answers.size() * 0.4;
            int cardinality40 = (int) Math.ceil(factor40);

            int goodCharmaCardinality = personService.getCardinality(p, Qbook.getInstance().getHasGoodCharmaURI());
            int badCharmaCardinality = personService.getCardinality(p, Qbook.getInstance().getHasBadCharmaURI());

            OWLObjectProperty hasBadAnswerProperty;
            OWLClassExpression hasBadAnswerClassLow;
            OWLClassExpression hasBadAnswerClassHigh;
            OWLObjectProperty hasDoubtAnswerProperty;
            OWLClassExpression hasDoubtAnswerClass;
            OWLObjectProperty hasTrustAnswerProperty;
            OWLClassExpression hasTrustAnswerClass;
            OWLObjectProperty hasSuperAnswerProperty;
            OWLClassExpression hasSuperAnswerClassLow;
            OWLClassExpression hasSuperAnswerClassHigh;

            // GOOD CHARMA
            if(goodCharmaCardinality >= cardinality80)
            {
                System.out.println("User has good Charma");
                hasBadAnswerProperty = dataFactory.getOWLObjectProperty(IRI.create(Qbook.getInstance().getHasBadAnswerURI().stringValue()));
                hasBadAnswerClassLow = dataFactory.getOWLObjectMinCardinality(cardinality60, hasBadAnswerProperty);
                hasBadAnswerClassHigh = dataFactory.getOWLObjectMinCardinality(cardinality90, hasBadAnswerProperty);

                hasDoubtAnswerProperty = dataFactory.getOWLObjectProperty(IRI.create(Qbook.getInstance().getHasDoubtAnswerURI().stringValue()));
                hasDoubtAnswerClass = dataFactory.getOWLObjectMinCardinality(cardinality90, hasDoubtAnswerProperty);

                hasTrustAnswerProperty = dataFactory.getOWLObjectProperty(IRI.create(Qbook.getInstance().getHasTrustAnswerURI().stringValue()));
                hasTrustAnswerClass = dataFactory.getOWLObjectMinCardinality(cardinality40, hasTrustAnswerProperty);

                hasSuperAnswerProperty = dataFactory.getOWLObjectProperty(IRI.create(Qbook.getInstance().getHasSuperAnswerURI().stringValue()));
                hasSuperAnswerClassLow = dataFactory.getOWLObjectMinCardinality(cardinality40, hasSuperAnswerProperty);
                hasSuperAnswerClassHigh = dataFactory.getOWLObjectMinCardinality(cardinality60, hasSuperAnswerProperty);

            }
            // BAD CHARMA
            else if(badCharmaCardinality >= cardinality80)
            {
                System.out.println("User has bad Charma");
                hasBadAnswerProperty = dataFactory.getOWLObjectProperty(IRI.create(Qbook.getInstance().getHasBadAnswerURI().stringValue()));
                hasBadAnswerClassLow = dataFactory.getOWLObjectMinCardinality(cardinality40, hasBadAnswerProperty);
                hasBadAnswerClassHigh = dataFactory.getOWLObjectMinCardinality(cardinality60, hasBadAnswerProperty);

                hasDoubtAnswerProperty = dataFactory.getOWLObjectProperty(IRI.create(Qbook.getInstance().getHasDoubtAnswerURI().stringValue()));
                hasDoubtAnswerClass = dataFactory.getOWLObjectMinCardinality(cardinality60, hasDoubtAnswerProperty);

                hasTrustAnswerProperty = dataFactory.getOWLObjectProperty(IRI.create(Qbook.getInstance().getHasTrustAnswerURI().stringValue()));
                hasTrustAnswerClass = dataFactory.getOWLObjectMinCardinality(cardinality60, hasTrustAnswerProperty);

                hasSuperAnswerProperty = dataFactory.getOWLObjectProperty(IRI.create(Qbook.getInstance().getHasSuperAnswerURI().stringValue()));
                hasSuperAnswerClassLow = dataFactory.getOWLObjectMinCardinality(cardinality60, hasSuperAnswerProperty);
                hasSuperAnswerClassHigh = dataFactory.getOWLObjectMinCardinality(cardinality90, hasSuperAnswerProperty);
            }
            // MEDIATE CHARMA
            else
            {
                System.out.println("User has mediate Charma");
                hasBadAnswerProperty = dataFactory.getOWLObjectProperty(IRI.create(Qbook.getInstance().getHasBadAnswerURI().stringValue()));
                hasBadAnswerClassLow = dataFactory.getOWLObjectMinCardinality(cardinality50, hasBadAnswerProperty);
                hasBadAnswerClassHigh = dataFactory.getOWLObjectMinCardinality(cardinality80, hasBadAnswerProperty);

                hasDoubtAnswerProperty = dataFactory.getOWLObjectProperty(IRI.create(Qbook.getInstance().getHasDoubtAnswerURI().stringValue()));
                hasDoubtAnswerClass = dataFactory.getOWLObjectMinCardinality(cardinality80, hasDoubtAnswerProperty);

                hasTrustAnswerProperty = dataFactory.getOWLObjectProperty(IRI.create(Qbook.getInstance().getHasTrustAnswerURI().stringValue()));
                hasTrustAnswerClass = dataFactory.getOWLObjectMinCardinality(cardinality80, hasTrustAnswerProperty);

                hasSuperAnswerProperty = dataFactory.getOWLObjectProperty(IRI.create(Qbook.getInstance().getHasSuperAnswerURI().stringValue()));
                hasSuperAnswerClassLow = dataFactory.getOWLObjectMinCardinality(cardinality50, hasSuperAnswerProperty);
                hasSuperAnswerClassHigh = dataFactory.getOWLObjectMinCardinality(cardinality80, hasSuperAnswerProperty);
            }

            reasoner.prepareReasoner();

            // TODO: ANZAHL konfigurierbar machen
            if(answers.size() > 5)
            {
                // Wenn mehr als n Antworten gegeben wurden und  >= 80% der Antworten SuperAnswers sind  wird der User
                // als ExpertUser klassifiziert

                for(Node<OWLNamedIndividual> cl : reasoner.getInstances(hasSuperAnswerClassHigh, true))
                {
                    for(OWLNamedIndividual ind : cl.getEntities())
                    {
                        if(ind.getIRI().toString().equals(p.getUri().stringValue()))
                        {
                            p.setUserClass(UserClass.ExpertUser);
                            personService.updateClassification(p);
                            personService.flush();
                            this.processReasoning(ReasoningType.Classes);
                            return;
                        }
                    }
                }
            }


            // Überprüfung ob >= 50% der Antworten SuperAnswers sind - wenn ja wird der User
            // als TrustUser klassifiziert

            for(Node<OWLNamedIndividual> cl : reasoner.getInstances(hasSuperAnswerClassLow, true))
            {
                for(OWLNamedIndividual ind : cl.getEntities())
                {
                    if(ind.getIRI().toString().equals(p.getUri().stringValue()))
                    {
                        p.setUserClass(UserClass.TrustUser);
                        personService.updateClassification(p);
                        personService.flush();
                        this.processReasoning(ReasoningType.Classes);
                        return;
                    }
                }
            }

//          Überprüfung ob >= 80% der Antworten TrustAnswers sind - wenn ja wird der User
//          als TrustUser klassifiziert

            for(Node<OWLNamedIndividual> cl : reasoner.getInstances(hasTrustAnswerClass, true))
            {
                for(OWLNamedIndividual ind : cl.getEntities())
                {
                    if(ind.getIRI().toString().equals(p.getUri().stringValue()))
                    {
                        p.setUserClass(UserClass.TrustUser);
                        personService.updateClassification(p);
                        personService.flush();
                        this.processReasoning(ReasoningType.Classes);
                        return;
                    }
                }
            }

//          Überprüfung ob >= 80% der Antworten BadAnswers sind - wenn ja wird der User
//          als BeginnerUser klassifiziert
            for(Node<OWLNamedIndividual> cl : reasoner.getInstances(hasBadAnswerClassHigh, true))
            {
                for(OWLNamedIndividual ind : cl.getEntities())
                {
                    if(ind.getIRI().toString().equals(p.getUri().stringValue()))
                    {
                        p.setUserClass(UserClass.BeginnerUser);
                        personService.updateClassification(p);
                        personService.flush();
                        this.processReasoning(ReasoningType.Classes);
                        return;
                    }
                }
            }

//          Überprüfung ob >= 50% der Antworten BadAnswers sind - wenn ja wird der User
//          als DoubtUser klassifiziert
            for(Node<OWLNamedIndividual> cl : reasoner.getInstances(hasBadAnswerClassLow, true))
            {
                for(OWLNamedIndividual ind : cl.getEntities())
                {
                    if(ind.getIRI().toString().equals(p.getUri().stringValue()))
                    {
                        p.setUserClass(UserClass.DoubtUser);
                        personService.updateClassification(p);
                        personService.flush();
                        this.processReasoning(ReasoningType.Classes);
                        return;
                    }
                }
            }

//          Überprüfung ob >= 80% der Antworten DoubtAnswers sind - wenn ja wird der User
//          als DoubtUser klassifiziert
            for(Node<OWLNamedIndividual> cl : reasoner.getInstances(hasDoubtAnswerClass, true))
            {
                for(OWLNamedIndividual ind : cl.getEntities())
                {
                    if(ind.getIRI().toString().equals(p.getUri().stringValue()))
                    {
                        p.setUserClass(UserClass.DoubtUser);
                        personService.updateClassification(p);
                        personService.flush();
                        this.processReasoning(ReasoningType.Classes);
                        return;
                    }
                }
            }

            // Bei allen andern Fällen wird der User als StdUser klassifiziert

            p.setUserClass(UserClass.StdUser);
            personService.updateClassification(p);
            personService.flush();
            this.processReasoning(ReasoningType.Classes);

        } catch (Exception re) {
            re.printStackTrace();
        }


    }

}
